package com.opengw.beans.support;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;

import javax.wsdl.Definition;
import javax.wsdl.Port;
import javax.wsdl.Service;
import javax.wsdl.Types;
import javax.wsdl.WSDLException;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;

import org.w3c.dom.Document;
import org.xml.sax.InputSource;

import com.ibm.wsdl.extensions.http.HTTPAddressImpl;
import com.ibm.wsdl.extensions.schema.SchemaImpl;
import com.ibm.wsdl.extensions.schema.SchemaImportImpl;
import com.ibm.wsdl.extensions.soap.SOAPAddressImpl;
import com.ibm.wsdl.extensions.soap12.SOAP12AddressImpl;
import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;

public class WSDLValidator {

	private Definition definition = null;
	private String endPointAddress;
	
	public WSDLValidator(byte[] wsdlContent) throws WSDLException{
		WSDLFactory factory = WSDLFactory.newInstance();
        WSDLReader reader = factory.newWSDLReader();
        reader.setFeature("javax.wsdl.verbose", false);
        reader.setFeature("javax.wsdl.importDocuments", true);
        
        InputSource source = new InputSource(new ByteArrayInputStream(wsdlContent));
        
        this.definition = reader.readWSDL(null, source);
        
        Map services = this.definition.getServices();
        Iterator iterator = services.keySet().iterator();
        while (iterator.hasNext()) {
            QName key = (QName) iterator.next();
            Service service = (Service) services.get(key);
            Map ports = service.getPorts();
            Iterator portIterator = service.getPorts().keySet().iterator();
            while (portIterator.hasNext()) {
                String subkey = (String) portIterator.next();
                Port port = (Port) ports.get(subkey);
                for (Object obj : port.getExtensibilityElements()) {
                    if (obj instanceof SOAPAddressImpl) {
                        SOAPAddressImpl soap = (SOAPAddressImpl) obj;
                        endPointAddress = soap.getLocationURI();
                    } else if (obj instanceof SOAP12AddressImpl) {
                        SOAP12AddressImpl soap = (SOAP12AddressImpl) obj;
                        endPointAddress = soap.getLocationURI();
                    } else if (obj instanceof HTTPAddressImpl) {
                        HTTPAddressImpl http = (HTTPAddressImpl) obj;
                        endPointAddress = http.getLocationURI();
                    } 
                }
            }
        }
	}
	
	public byte[] toByteArray() throws Exception{
		
		WSDLFactory factory = WSDLFactory.newInstance();
		Document doc = factory.newWSDLWriter().getDocument(definition);
		
		OutputFormat format = new OutputFormat(doc);
        format.setIndenting(true);
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        XMLSerializer serializer = new XMLSerializer(outStream, format);
        serializer.serialize(doc);
        
        return outStream.toByteArray();
	}
	
	public void changeEndPointLocationURI(String endPointURL){
		Map services = this.definition.getServices();
        Iterator iterator = services.keySet().iterator();
        while (iterator.hasNext()) {
            QName key = (QName) iterator.next();
            Service service = (Service) services.get(key);
            Map ports = service.getPorts();
            Iterator portIterator = service.getPorts().keySet().iterator();
            while (portIterator.hasNext()) {
                String subkey = (String) portIterator.next();
                Port port = (Port) ports.get(subkey);
                for (Object obj : port.getExtensibilityElements()) {
                    if (obj instanceof SOAPAddressImpl) {
                        SOAPAddressImpl soap = (SOAPAddressImpl) obj;
                        soap.setLocationURI(endPointURL);
                    } else if (obj instanceof SOAP12AddressImpl) {
                        SOAP12AddressImpl soap = (SOAP12AddressImpl) obj;
                        soap.setLocationURI(endPointURL);
                    } else if (obj instanceof HTTPAddressImpl) {
                        HTTPAddressImpl http = (HTTPAddressImpl) obj;
                        http.setLocationURI(endPointURL);
                    } 
                }
            }
        }
	}

	public String getEndPointAddress() {
		return endPointAddress;
	}
}
